package org.fing.edu.uy.esbadp.action.list;

import java.util.List;
import java.util.UUID;
import java.util.logging.Level;

import org.fing.edu.uy.esbadp.assertion.AssertProperty;
import org.fing.edu.uy.esbadp.core.AdpFlowConstants;
import org.fing.edu.uy.esbadp.core.AdpFlowInterface;
import org.fing.edu.uy.esbadp.core.AdpFlowTree;
import org.fing.edu.uy.esbadp.core.constants.EsbAdpPropertyConstants;
import org.fing.edu.uy.esbadp.core.entity.GenericTreeNode;
import org.fing.edu.uy.esbadp.logger.LoggerADP;
import org.jboss.internal.soa.esb.assertion.AssertArgument;
import org.jboss.soa.esb.actions.ActionProcessingException;
import org.jboss.soa.esb.actions.annotation.Process;
import org.jboss.soa.esb.client.ServiceInvoker;
import org.jboss.soa.esb.message.Message;

public class ListAction {

	private static java.util.logging.Logger logger = LoggerADP.getLogger(ListAction.class.getSimpleName());
			
	public ListAction() {
		
	}	
	
	/**
	 * @param message
	 */
	@Process
	public Message process(Message message) throws ActionProcessingException {
		
		if(logger.isLoggable(LoggerADP.DEBUG_LEVEL)){
			logger.log(LoggerADP.DEBUG_LEVEL, "Process Action -> {0}", this.getClass().getName());
		}
		
		AssertArgument.isNotNull(message, "message");
		AssertProperty.isNotNull(message, AdpFlowConstants.PropertyFlowServices);

		try {
			// se obtiene tree de propiedades
			AdpFlowTree adpFlowTree = (AdpFlowTree) message.getProperties().getProperty(AdpFlowConstants.PropertyFlowServices);

			// agrego un ID para identificar las respuestas ,si existe uno realizamos un stack separados por coma.
			UUID messageInternalUUID = UUID.randomUUID();
			String oldUUID = (String) message.getProperties().getProperty(EsbAdpPropertyConstants.AGGEGRATOR_UUID_MESSAGE,"");
			StringBuilder sb = new StringBuilder(messageInternalUUID.toString());
			sb.append(",");
			sb.append(oldUUID);
			
			message.getProperties().setProperty(EsbAdpPropertyConstants.AGGEGRATOR_UUID_MESSAGE, sb.toString());

			// voy a obtener la lista de hijos de el nodo.
			GenericTreeNode<AdpFlowInterface> treeNode = adpFlowTree.getCurrent();
			List<GenericTreeNode<AdpFlowInterface>> childrens = treeNode.getChildren();

			int idCall = 0;
			//para cada nodo voy a llamar asincronicamente al servicio que sigue.
			for (GenericTreeNode<AdpFlowInterface> treeAux : childrens) {
				
				// genero una copia del mensaje para poder procesarlos de forma
				// independiente en cada flujo
				Message auxMessage = message.copy();
				auxMessage.getProperties().setProperty(EsbAdpPropertyConstants.AGGEGRATOR_ID_MESSAGE, idCall);
				
				//sustituyo el flujo por la rama que quiero invocar
				AdpFlowTree flujoAux =  new AdpFlowTree(adpFlowTree);							
				
				flujoAux.setCurrent(treeAux);
				auxMessage.getProperties().setProperty(AdpFlowConstants.PropertyFlowServices, flujoAux);	

				ServiceInvoker srvIn = new ServiceInvoker(treeAux.getData().getServiceCategoryName(),treeAux.getData().getServiceName());
				srvIn.deliverAsync(auxMessage);
				idCall++;
			}
		} catch (Exception ex) {
			logger.log(Level.SEVERE,"Exception in ListAction when delivery Async Message", ex);
		}
		return null;
	}

}
